package IA.GA.editorial;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.jgap.Chromosome;
import org.jgap.Configuration;
import org.jgap.Genotype;
import org.jgap.InvalidConfigurationException;

import IA.GA.editorial.domain.BookFitnes;
import IA.GA.util.CustomMap;
import IA.GA.util.Helper;

public class App
{
	public static double sumFitness=0; 
	static Genotype population = null;
	private static List<Double> listindFitness = new ArrayList<Double>();
	static CustomMap<Integer, AbstractConfigFactory> factoryStrategy = new CustomMap<Integer, AbstractConfigFactory>().put(1, new Config1()).put(2, new Config2()).put(3, new Config3()).put(4, new Config4()).put(5, new Config5());
	
	
	public static void main(String[] args) throws Exception {
	BufferedWriter output = new BufferedWriter(new FileWriter(new File("fitnessValConf"+getFactory(args)+"Initpob"+getPoblacionSize(args)+"IT"+getIteraciones(args)+".csv")));
	BufferedWriter outputNorm = new BufferedWriter(new FileWriter(new File("fitnessNORMConf"+getFactory(args)+"Pobsz"+getPoblacionSize(args)+"IT"+getIteraciones(args)+".csv")));
	BufferedWriter outputPob = new BufferedWriter(new FileWriter(new File("PobSize"+getFactory(args)+"Initpobsz"+getPoblacionSize(args)+"IT"+getIteraciones(args)+".csv")));
	BufferedWriter outputChrom = new BufferedWriter(new FileWriter(new File("BestChrom"+getFactory(args)+"Initpobsz"+getPoblacionSize(args)+"IT"+getIteraciones(args)+".txt")));
	
	population = setEnviroment(args);
	
	 for(int i = 0; i < getIteraciones(args); i++){
		 population.evolve();		 
		 printPopulatonSize(outputPob);
	 }
	 
	 printFitness(output, outputNorm);
	 printBestChromosomes(args, outputChrom);
	 	 
	 outputChrom.close();
	 output.close();
	 outputNorm.close();
	 outputPob.close();
	 }

	public static void printPopulatonSize(BufferedWriter outputPob)
			throws IOException {
		double fitness = population.getFittestChromosome().getFitnessValue();
		 sumFitness += fitness;		 
		 listindFitness.add(fitness);		 
		 outputPob.write(population.getPopulation().size()+";\n");
	}

	public static void printFitness(BufferedWriter output,
			BufferedWriter outputNorm) throws IOException {
		for(Double indfit : listindFitness){
			 outputNorm.write(Double.toString((indfit.doubleValue()/sumFitness)*100) + ";\n");
			 output.write(Math.round(indfit) + ";\n");
		 }
	}

	public static Genotype setEnviroment(String[] args) throws InvalidConfigurationException{		
		Configuration conf = factoryStrategy.get(getFactory(args)).getConfig(getPoblacionSize(args));		
		conf.setFitnessFunction(new BookFitnes(getPoblacionSize(args),getIteraciones(args)));
		Genotype population = Genotype.randomInitialGenotype(conf);			
		return population;
	}
	
	public static void printBestChromosomes(String[] args,
			BufferedWriter outputChrom) throws IOException {
		List<Chromosome> chromosomas= population.getFittestChromosomes(3);
		
		 outputChrom.write(new Date()+"\n");
		 outputChrom.write("Cantidad de poblacion inicial: "+getPoblacionSize(args)+"\n");
		 outputChrom.write("Cantidad de iteraciones: "+getIteraciones(args)+"\n");
		 outputChrom.write("Configuracion: "+getFactory(args)+"\n");
		 for(Chromosome chrome : chromosomas){
			 
			 outputChrom.write("<========================**************=====================>");
			 outputChrom.newLine();
			 outputChrom.write("<========================OLGA=====================>");
			 outputChrom.newLine();
			 outputChrom.write("Idioma: "+ Helper.instance.getIdioma(Helper.instance.getGeneOlga(chrome).getIdiomaGen()));
			 outputChrom.newLine();
			 outputChrom.write("Cantidad de Paginas: "+Helper.instance.getCantPaginas(Helper.instance.getGeneOlga(chrome).getCantPaginasGen()));
			 outputChrom.newLine();
			 outputChrom.write("Tipo de Libro: "+Helper.instance.getTipoDeLibro(Helper.instance.getGeneOlga(chrome).getTipoLibroGen()));
			 outputChrom.newLine();
			 outputChrom.write("Longitud de libro: "+Helper.instance.getLongitudLibro(Helper.instance.getGeneOlga(chrome).getLongitudGen()));
			 outputChrom.newLine();
			 outputChrom.write("<=================================================>");
			 outputChrom.newLine();
			 outputChrom.write("<========================SILVIA====================>");
			 outputChrom.newLine();
			 outputChrom.write("Idioma: "+ Helper.instance.getIdioma(Helper.instance.getGeneSilvia(chrome).getIdiomaGen()));
			 outputChrom.newLine();
			 outputChrom.write("Cantidad de Paginas: "+Helper.instance.getCantPaginas(Helper.instance.getGeneSilvia(chrome).getCantPaginasGen()));
			 outputChrom.newLine();
			 outputChrom.write("Tipo de Libro: "+Helper.instance.getTipoDeLibro(Helper.instance.getGeneSilvia(chrome).getTipoLibroGen()));
			 outputChrom.newLine();
			 outputChrom.write("Longitud de libro: "+Helper.instance.getLongitudLibro(Helper.instance.getGeneSilvia(chrome).getLongitudGen()));
			 outputChrom.newLine();
			 outputChrom.write("<=================================================>");
			 outputChrom.newLine();
			 outputChrom.write("<========================JUAN=====================>");
			 outputChrom.newLine();
			 outputChrom.write("Idioma: "+ Helper.instance.getIdioma(Helper.instance.getGeneJuan(chrome).getIdiomaGen()));
			 outputChrom.newLine();
			 outputChrom.write("Cantidad de Paginas: "+Helper.instance.getCantPaginas(Helper.instance.getGeneJuan(chrome).getCantPaginasGen()));
			 outputChrom.newLine();
			 outputChrom.write("Tipo de Libro: "+Helper.instance.getTipoDeLibro(Helper.instance.getGeneJuan(chrome).getTipoLibroGen()));
			 outputChrom.newLine();
			 outputChrom.write("Longitud de libro: "+Helper.instance.getLongitudLibro(Helper.instance.getGeneJuan(chrome).getLongitudGen()));
			 outputChrom.newLine();
			 outputChrom.write("<=================================================>");
			 outputChrom.newLine();
			 outputChrom.write("Fitness Value: "+ Math.round(chrome.getFitnessValue()));
			 outputChrom.newLine();
			 outputChrom.write("<========================**************=====================>");
			 outputChrom.newLine();
		 }
		 	System.out.println("<=========Listo========>");
		 	System.out.println("<========="+new Date()+"========>");
	}
	
	
	public static Integer getFactory(String[] args){
		return args.length >=1 && Integer.parseInt(args[0].toString()) >= 1 && Integer.parseInt(args[0].toString()) <= 5? Integer.parseInt(args[0].toString()) : 1;		
	}
	
	public static Integer getPoblacionSize(String[] args){		
		return (args.length >=2 ? Integer.parseInt(args[1].toString()) : 54);
		
	}
	
	public static Integer getIteraciones(String[] args){
		return args.length >=3  && Integer.parseInt(args[2].toString()) > 0 ? Integer.parseInt(args[2].toString()) : 500; 
	}
		
}
